package com.kmxd.ams.core.aspect;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.kmxd.ams.core.common.constant.ArchConst;
import com.kmxd.ams.core.util.DynamicTableNameUtil;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.stereotype.Service;

/**
 * 动态表明切面
 *
 * @author ZuoLG
 */
@Slf4j
@Aspect
@Service("DynamicTableAspect")
public class DynamicTableAspect {

  @Pointcut("execution(* com.kmxd.ams.app.arrange.*.*(..))")
  public void anyMethod() {}

  /**
   * 方法的前置通知
   *
   * @param joinPoint
   */
  @Before("anyMethod()")
  public void before(JoinPoint joinPoint) {
    try {
      Object[] args = joinPoint.getArgs();
      String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
      if (args.length == 0) {
        return;
      }

      JSONObject jsonObject = null;
      String amsTableId = null;
      for (int i = 0; i < args.length; i++) {
        Object arg = args[i];
        String paramName = paramNames[i];
        // 如果参数为基础类型，直接设置表名
        if (paramName.equals(ArchConst.TABLE_ID)) {
          DynamicTableNameUtil.setTableName(String.valueOf(arg));
          return;
        }
        if (arg instanceof HashSet || arg instanceof ArrayList) {
          return;
        }
        // 参数为对象或其他非基础类型数据
        jsonObject = JSONUtil.parseObj(arg);
        amsTableId = jsonObject.getStr(ArchConst.TABLE_ID);
        if (StrUtil.isNotBlank(amsTableId)) {
          List<String> fields = Lists.newArrayList();
//          List<String> fields = Lists.newArrayList("test");
          DynamicTableNameUtil.setTableName(amsTableId, fields);
          return;
        }
      }
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }
  }

  /** 后置通知 */
  @AfterReturning("anyMethod()")
  public void afterMethod() {}

  /**
   * 异常通知
   *
   * @throws Throwable
   */
  @AfterThrowing("anyMethod()")
  public void afterThrowing() throws Throwable {}

  /** 最终通知 */
  @After("anyMethod()")
  public void finalMethod() {}
}
